# 导入selenium
import base64
import os
import shutil
import time
import cv2
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.edge.service import Service as EdgeService
from webdriver_manager.microsoft import EdgeChromiumDriverManager
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from tqdm import trange
from img2pdf import conpdf
from match2png import conmatch,get_tracks

def download(url):
    # 浏览器启动参数设置
    options = webdriver.EdgeOptions()
    # 设置user-agent
    user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0'
    options.add_argument(f'user-agent={user_agent}')
    # 禁用浏览器中的自动化检测
    options.add_experimental_option("excludeSwitches", ['enable-automation', 'enable-logging'])
    options.add_experimental_option('useAutomationExtension', False)
    options.add_argument('--disable-blink-features=AutomationControlled')
    # 禁止显示保存密码提示框
    prefs = {"credentials_enable_service": False, "profile.password_manager_enabled": False}
    options.add_experimental_option("prefs", prefs)
    # 不关闭网页
    options.add_experimental_option("detach", True)
    # 最大化运行（全屏窗口）,不设置，取元素会报错
    options.add_argument('--start-maximized')
    driver = webdriver.Edge(options =options,service=EdgeService(EdgeChromiumDriverManager().install())) # => 打开浏览器时加入配置
    # 避免被浏览器检测出来使用了Selenium
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
        })
    """
    })
    title = "output"
    try:
        driver.set_page_load_timeout(15)# 页面加载超时时间
        driver.get(url)
        time.sleep(1)
        title = driver.title
        if title == '验证':
            time.sleep(20)
    except:
        print("Timeout - start download anyway.")
    # 去掉特殊字符/\:*?"<>|
    sets = ['/', '\\', ':', '*', '?', '"', '<', '>', '|']
    for char in title:
        if char in sets:
            title = title.replace(char, '')
    print(f'道客巴巴: 《{title}》')
    time.sleep(5)
    # right-menu => 进入幻灯片模式可以跳过滑动图形验证码
    try:
        elem_cont_button = driver.find_element(By.ID, 'dragdrop')# 定位到屏幕覆盖保护块
        time.sleep(0.5)
        ActionChains(driver).context_click(elem_cont_button).perform()# 右键
        elem_cont_button = driver.find_element(By.ID, 'rmenu_ppt')# 定位到“进入幻灯片模式”按钮
        time.sleep(0.5)
        ActionChains(driver).click(elem_cont_button).perform()# 单击鼠标左键，进入幻灯片模式。
        time.sleep(5)
    except NoSuchElementException:
        pass
    # 展开文档全部内容
    try:
        elem_cont_button = driver.find_element(By.ID, "continueButton")# 定位到“继续免费阅读全文”按钮
        time.sleep(0.5)
        driver.execute_script("arguments[0].scrollIntoView(true);", elem_cont_button)# 移动到按钮的“顶端”与当前窗口的“顶部”对齐
        if not EC.element_to_be_clickable((By.ID, "continueButton")):
            driver.execute_script("arguments[0].scrollIntoView(false);", elem_cont_button)# 移动到按钮的“底端”与当前窗口的“底部”对齐
            time.sleep(0.5)
        ActionChains(driver).click(elem_cont_button).perform()# 单击鼠标左键
    except NoSuchElementException:
        pass
    time.sleep(5)
    # 获取页数
    num_of_pages = driver.find_element(By.CLASS_NAME, 'text')
    # 放大
    for i in range(5):
        # 缩放
        driver.find_element(By.ID, 'zoomInButton').click()
        time.sleep(0.5)
    # 检查文件和文件夹
    if os.path.exists(f'./temp/{title}'):# 查看给定的文件/目录是否存在
        shutil.rmtree(f'./temp/{title}')# 存在，递归删除文件夹下的所有子文件夹和子文件
    os.makedirs(f'./temp/{title}')# 不存在，递归创建目录    
    if not os.path.exists(f'output'):# 查看给定的文件/目录是否存在
        os.makedirs(f'output')# 不存在，递归创建目录        
    if os.path.exists(f'./output/{title}.pdf'):# 查看给定的文件/目录是否存在
        os.remove(f'./output/{title}.pdf')# 删除指定路径的文件
    # 下载图片文件
    for pages in trange(int (num_of_pages.text.replace('/ ','') )):
        time.sleep(0.5)
        canvas_id = "page_" + str(pages + 1)
        pagepb_id = "pagepb_" + str(pages + 1)
        element = driver.find_element(By.ID, canvas_id)# 定位到每一页
        driver.execute_script("arguments[0].scrollIntoView(true);", element)# 移动到每一页的“顶端”与当前窗口的“顶部”对齐
        actions = ActionChains(driver)# 模拟鼠标操作
        actions.move_to_element(element).perform()# 鼠标移动到该页
        time.sleep(0.5)
        while (len(driver.find_element(By.ID, pagepb_id).text) != 0):# 等待页面加载完成
            time.sleep(1)
            print(driver.find_element(By.ID, pagepb_id).text)
        # “getElementById(id)” 通过元素的 id 属性获取文档中对应的 HTML 元素，返回的是一个包含该元素的引用
        # “toDataURL()” 返回一个数据 URL，其中包含参数指定格式的图像表示形式。
        js_cmd = "var canvas = document.getElementById('{}');".format(canvas_id) + "return canvas.toDataURL();"
        # print(js_cmd)
        img_data = driver.execute_script(js_cmd)# 执行JavaScript代码，图片转换为Base64编码
        # print(img_data)
        img_data = (img_data[22:]).encode()# <data:image/png;base64,>得到图片的base64
        # print(img_data)
        with open(f"./temp/{title}/{pages}.png", "wb") as fh:
            fh.write(base64.decodebytes(img_data))# 解码图片的base64
    # 关闭浏览器
    driver.quit()
    # PNG转PDF
    print('下载完毕，正在转码')
    conpdf(f'output/{title}.pdf', f'temp/{title}', '.png')